.global _start
#if 0
.global _bss_start

_bss_start:
	.word __bss_start

.global _bss_end
_bss_end:
	.word __bss_end
#endif

_start:
	ldr pc,=Reset_Handler		//reset interrupt
	ldr pc,=Undefined_Handler
	ldr pc,=SVC_Handler
	ldr pc,=PreAbort_Handler
	ldr pc,=DataAbort_Handler
	ldr pc,=NotUsed_Handler
	ldr pc,=IRQ_Handler
	ldr pc,=FIQ_Handler

//reset handler interrupt
Reset_Handler:
	cpsid i			/* close globle interrupt */
	//1.turn off Icache Dcache MMU		CP15 help_register	modify SCTLR reg read->modify->write
	mrc p15,0,r0,c1,c0,0	//read
	bic r0,r0,#(1 << 12)	//turn off I cache
	bic r0,r0,#(1 << 2)	//turn off D cache
	bic r0,r0,#0x2		//turn off alien
	bic r0,r0,#(1 << 11)	//turn off branch predition
	bic r0,r0,#0x1		//turn off MMU
	mcr p15,0,r0,c1,c0,0    //write
#if 0
	//2.set interrupt vertor offset
	ldr r0,=0x87800000
	dsb
	isb
	MCR p15,0,r0,c12,c0,0	//read
	dsb
	isb
#endif

#if 0
	//clear bss
	ldr r0,_bss_start
	ldr r1,_bss_end
	mov r2,#0

bss_loop:
	stmia r0!,{r2}
	cmp r0,r1			//compare the value in r0&r1
	ble bss_loop
#endif
	/* enter irq mode */
	mrs r0, cpsr
	bic r0, r0, #0x1f	/* 将r0寄存器中的低5位清零，也就是cpsr的M0~M4	*/
	orr r0, r0, #0x12	/* r0或上0x12,表示使用irq模式					*/
	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中					*/
	ldr sp,=0X80600000

	/* enter sys mode */
	mrs r0, cpsr
	bic r0, r0, #0x1f	/* 将r0寄存器中的低5位清零，也就是cpsr的M0~M4*/
	orr r0, r0, #0x1f	/* r0或上0x1f,表示使用sys模式				*/
	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中					*/
	ldr sp,=0X80400000

	/* enter SVC mode */
	mrs r0, cpsr
	bic r0, r0, #0x1f	/* 将r0寄存器中的低5位清零，也就是cpsr的M0~M4	*/
	orr r0, r0, #0x13	/* r0或上0x13,表示使用SVC模式					*/
	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中					*/
	ldr sp,=0X80200000

	cpsie i				/* 打开全局中断 */
	b main				/* JUMP to main函数 	*/

//undefine handler interrupt
Undefined_Handler:
	ldr r0, =Undefined_Handler
	bx	r0

//svc handler interrupt
SVC_Handler:
	ldr r0, =SVC_Handler
	bx	r0

//preabort handler interrupt
PreAbort_Handler:
	ldr r0, =PreAbort_Handler
	bx	r0

//data abort handler interrupt
DataAbort_Handler:
	ldr r0, =DataAbort_Handler
	bx	r0

//not used handler interrupt
NotUsed_Handler:
	ldr r0, =NotUsed_Handler
	bx	r0

//irq handler interrupt
IRQ_Handler:
	push {lr}					/* 保存lr地址 */
	push {r0-r3, r12}			/* 保存r0-r3，r12寄存器 */

	mrs r0, spsr				/* 读取spsr寄存器 */
	push {r0}					/* 保存spsr寄存器 */

	mrc p15, 4, r1, c15, c0, 0 /* 从CP15的C0寄存器内的值到R1寄存器中
								* 参考文档ARM Cortex-A(armV7)编程手册V4.0.pdf P49
								* Cortex-A7 Technical ReferenceManua.pdf P68 P138
								*/							
	add r1, r1, #0X2000			/* GIC基地址加0X2000，也就是GIC的CPU接口端基地址 */
	ldr r0, [r1, #0XC]			/* GIC的CPU接口端基地址加0X0C就是GICC_IAR寄存器，
								 * GICC_IAR寄存器保存这当前发生中断的中断号，我们要根据
								 * 这个中断号来绝对调用哪个中断服务函数
								 */
	push {r0, r1}				/* 保存r0,r1 */
	
	cps #0x13					/* 进入SVC模式，允许其他中断再次进去 */
	
	push {lr}					/* 保存SVC模式的lr寄存器 */
	ldr r2, =system_irqhandler	/* 加载C语言中断处理函数到r2寄存器中*/
	blx r2						/* 运行C语言中断处理函数，带有一个参数，保存在R0寄存器中 */

	pop {lr}					/* 执行完C语言中断服务函数，lr出栈 */
	cps #0x12					/* 进入IRQ模式 */
	pop {r0, r1}				
	str r0, [r1, #0X10]			/* 中断执行完成，写EOIR,STR 将R0 的 值写到 R1 的 0x10中的地址寄存器中*/

	pop {r0}						
	msr spsr_cxsf, r0			/* 恢复spsr */

	pop {r0-r3, r12}			/* r0-r3,r12出栈 */
	pop {lr}					/* lr出栈 */
	subs pc, lr, #4				/* 将lr-4赋给pc */

//fiq handler interrupt
FIQ_Handler:
	ldr r0, =FIQ_Handler
	bx	r0

